import { fileURLToPath, URL } from 'node:url'
import path from 'node:path'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import AutoImport from 'unplugin-auto-import/vite'
import VueRouter from 'unplugin-vue-router/vite'
import { VueRouterAutoImports } from 'unplugin-vue-router'
import Layouts from 'vite-plugin-vue-layouts'
import Components from 'unplugin-vue-components/vite'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import UnoCSS from 'unocss/vite'
import { viteMockServe } from 'vite-plugin-mock'
import { VitePWA } from 'vite-plugin-pwa'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    rollupOptions: {
      external: (id) => customExternals(id)
    }
  },
  plugins: [
    //https://github.com/posva/unplugin-vue-router#configuration
    VueRouter({
      // Folder(s) to scan for vue components and generate routes. Can be a string, or
      // an object, or an array of those. Each option allows to override global options.
      // like exclude, extensions, etc.
      routesFolder: 'src/views',

      // allowed extensions for components to be considered as pages
      // can also be a suffix: e.g. `.page.vue` will match `home.page.vue`
      // but remove it from the route path
      // extensions: ['.vue'],

      // list of glob files to exclude from the routes generation
      // e.g. ['**/__*'] will exclude all files and folders starting with `__`
      // e.g. ['**/__*/**/*'] will exclude all files within folders starting with `__`
      // e.g. ['**/*.component.vue'] will exclude components ending with `.component.vue`
      // exclude: [],

      // Path for the generated types. Defaults to `./typed-router.d.ts` if typescript
      // is installed. Can be disabled by passing `false`.
      // dts: './typed-router.d.ts',

      // Override the name generation of routes. unplugin-vue-router exports two versions:
      // `getFileBasedRouteName()` (the default) and `getPascalCaseRouteName()`. Import any
      // of them within your `vite.config.ts` file.
      // getRouteName: (routeNode) => myOwnGenerateRouteName(routeNode),

      // Customizes the default langage for `<route>` blocks
      // json5 is just a more permissive version of json
      // routeBlockLang: 'json5',

      // Change the import mode of page components. Can be 'async', 'sync', or a function with the following signature:
      // (filepath: string) => 'async' | 'sync'
      // importMode: 'async',
    }),
    // ⚠️ Vue must be placed after VueRouter()
    vue({
      script: {
        defineModel: true,
        propsDestructure: true
      }
    }),
    vueJsx(),
    //https://github.com/unplugin/unplugin-icons#unplugin-icons
    Icons({
      //https://github.com/unplugin/unplugin-icons#icons-data
      autoInstall: true
    }),
    UnoCSS(),
    //https://github.com/unplugin/unplugin-auto-import#configuration
    AutoImport({
      include: [
        /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
        /\.vue$/,
        /\.vue\?vue/, // .vue
        /\.md$/ // .md
      ],

      // global imports to register
      imports: [
        //region presets

        //内置预设详见：
        //  node_modules/.pnpm/unplugin-auto-import@0.16.6/node_modules/unplugin-auto-import/dist/types.d.ts
        //  https://github.com/unplugin/unplugin-auto-import/tree/main/src/presets
        'vue',

        //region https://github.com/posva/unplugin-vue-router#auto-imports
        // 'vue-router'
        VueRouterAutoImports,
        //endregion

        '@vueuse/core',

        //endregion
      ],

      resolvers: [ElementPlusResolver()]
    }),
    //https://github.com/unplugin/unplugin-vue-components#configuration
    Components({
      // relative paths to the directory to search for components.
      // dirs: ['src/components'],
      //文件夹的名字会作为组件名的前缀
      directoryAsNamespace: false,
      //如果文件夹的名字和组件本身的名字的前缀重复就不再追加文件夹的名字作为前缀
      collapseSamePrefixes: true,
      resolvers: [
        //unplugin-icons
        IconsResolver({
          prefix: 'i'
        }),
        ElementPlusResolver()
      ]
    }),
    Layouts({
      layoutsDirs: 'src/layouts',
      defaultLayout: 'none'
    }),
    viteMockServe({
      mockPath: 'mock',
      // enable: true
    }),
    VitePWA({
      manifest: {
        name: 'Vite App',
        short_name: 'Vite App',
        theme_color: '#ffffff',
        icons: [
          {
            src: '/192x192.png',
            sizes: '192x192',
            type: 'image/png'
          },
          {
            src: '/512x512.png',
            sizes: '512x512',
            type: 'image/png'
          }
        ]
      },
      registerType: 'autoUpdate'
    }),
    // https://github.com/vbenjs/vite-plugin-svg-icons/tree/main#readme
    createSvgIconsPlugin({
      // 指定需要缓存的图标文件夹
      iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      // 指定symbolId格式
      symbolId: 'icon-[dir]-[name]'
    })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

function customExternals(id: string) {
  const whiteList = [
    //Test.vue -> <img src="/api/image" alt="">, 此图片并不存在, 而是来自于我们 mock/test.ts
    '/api/image'
  ];
  if (whiteList.includes(id)) {
    return true
  }
  // 其他的外部依赖
  return false
}